using System.Collections.Generic;
using System.Net;
using CodePlex.TfsLibrary.ObjectModel;
using CodePlex.TfsLibrary.RepositoryWebSvc;
using CodePlex.UnitTestUtility;
using Xunit;

namespace CodePlex.TfsLibrary.ClientEngine
{
    class TestableTfsEngine : TfsEngine
    {
        public MockFileSystem FileSystem;
        public StubIgnoreList IgnoreList;
        public StubSourceControlService SourceControlService;
        List<SourceItemCallbackData> StatusWithServer__CallbackData;
        bool StatusWithServer__Stubbed = false;
        public string StatusWithServer_LocalPath;
        public bool StatusWithServer_Recursive;
        public VersionSpec StatusWithServer_Version;
        bool Update__Stubbed = false;
        public string Update_LocalPath;
        public bool Update_Recursive;
        public VersionSpec Update_Version;
        public string ValidateDirectoryStructure_Directory;
        public StubWebTransferService WebTransferService;

        TestableTfsEngine(StubSourceControlService sourceService,
                          StubWebTransferService webService,
                          MockFileSystem fileService,
                          StubIgnoreList ignoreList)
            : base(sourceService, webService, fileService, ignoreList, null)
        {
            SourceControlService = sourceService;
            WebTransferService = webService;
            FileSystem = fileService;
            IgnoreList = ignoreList;
        }

        public new TfsState TfsState
        {
            get { return base.TfsState; }
        }

        public static void AssertCorrectChunk(DiffEngine.Chunk chunk,
                                              DiffEngine.ChunkType type,
                                              params string[] lines)
        {
            Assert.Equal(type, chunk.ChunkType);
            Assert.Equal(lines.Length, chunk.LineCount);

            for (int idx = 0; idx < lines.Length; idx++)
                Assert.Equal(lines[idx], chunk.Lines[idx]);
        }

        public static TestableTfsEngine Create()
        {
            MockFileSystem fileSystem = new MockFileSystem();
            return new TestableTfsEngine(new StubSourceControlService(), new StubWebTransferService(fileSystem), fileSystem, new StubIgnoreList());
        }

        public new ICredentials GetCredentials(string tfsUrl)
        {
            return base.GetCredentials(tfsUrl);
        }

        public new ICredentials GetCredentials(string tfsUrl,
                                               bool force)
        {
            return base.GetCredentials(tfsUrl, force);
        }

        public new SourceItem[] QueryItems(string tfsUrl,
                                           string serverPath,
                                           RecursionType recursion,
                                           VersionSpec version)
        {
            return base.QueryItems(tfsUrl, serverPath, recursion, version);
        }

        public new TfsWorkspace SetupWorkspace(string localPath,
                                               bool includePendingEdits)
        {
            return base.SetupWorkspace(localPath, includePendingEdits);
        }

        protected override void StatusWithServer(string localPath,
                                                 VersionSpec version,
                                                 bool recursive,
                                                 SourceItemCallback callback)
        {
            if (StatusWithServer__Stubbed)
            {
                StatusWithServer_LocalPath = localPath;
                StatusWithServer_Version = version;
                StatusWithServer_Recursive = recursive;

                foreach (SourceItemCallbackData data in StatusWithServer__CallbackData)
                    callback(data.SourceItem, data.SourceItemResult);

                return;
            }

            base.StatusWithServer(localPath, version, recursive, callback);
        }

        public void StubQueryItems(params SourceItem[] items)
        {
            SourceControlService.QueryItems__Result = items;
        }

        public void StubStatusWithServer(params SourceItem[] items)
        {
            StatusWithServer__Stubbed = true;
            StatusWithServer__CallbackData = new List<SourceItemCallbackData>();

            foreach (SourceItem item in items)
                StatusWithServer__CallbackData.Add(new SourceItemCallbackData(item, SourceItemResult.S_Ok));
        }

        public void StubUpdate()
        {
            Update__Stubbed = true;
        }

        public override void Update(string localPath,
                                    bool recursive,
                                    VersionSpec version,
                                    UpdateCallback callback)
        {
            if (Update__Stubbed)
            {
                Update_LocalPath = localPath;
                Update_Recursive = recursive;
                Update_Version = version;
            }
            else
                base.Update(localPath, recursive, version, callback);
        }

        public override void ValidateDirectoryStructure(string directory)
        {
            ValidateDirectoryStructure_Directory = directory;

            base.ValidateDirectoryStructure(directory);
        }
    }
}